home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / CBASE102.ARJ / BOPS.C < prev    next >
Text File  |  1991-09-23  |  14KB  |  619 lines

  1. /*    Copyright (c) 1989 Citadel    */
  2. /*       All Rights Reserved        */
  3.  
  4. /* #ident    "@(#)bops.c    1.5 - 91/09/23" */
  5.  
  6. #include <ansi.h>
  7.  
  8. /* ansi headers */
  9. #include <errno.h>
  10. #ifdef AC_STDDEF
  11. #include <stddef.h>
  12. #endif
  13. #ifdef AC_STDLIB
  14. #include <stdlib.h>
  15. #endif
  16. #ifdef AC_STRING
  17. #include <string.h>
  18. #endif
  19.  
  20. /* non-ansi headers */
  21. #include <bool.h>
  22.  
  23. /* local headers */
  24. #include "blkio_.h"
  25.  
  26. /*man---------------------------------------------------------------------------
  27. NAME
  28.      b_alloc - allocate memory for block file
  29.  
  30. SYNOPSIS
  31.      #include "blkio_.h"
  32.  
  33.      int b_alloc(bp)
  34.      BLKFILE *bp;
  35.  
  36. DESCRIPTION
  37.      The b_alloc function allocates the memory needed by bp.  The
  38.      memory is initialized to all zeros.  A call to b_alloc should
  39.      normally be followed by a call to b_initlist to construct the
  40.      linked list for LRU replacement.
  41.  
  42.      b_alloc will fail if one or more of the following is true:
  43.  
  44.      [EINVAL]       bp is not a valid BLKFILE pointer.
  45.      [ENOMEM]       Enough memory is not available for
  46.                     allocation by the calling process.
  47.      [BENOPEN]      bp is not open.
  48.  
  49. SEE ALSO
  50.      b_free, b_initlist.
  51.  
  52. DIAGNOSTICS
  53.      Upon successful completion, a value of 0 is returned.  Otherwise,
  54.      a value of -1 is returned, and errno set to indicate the error.
  55.  
  56. ------------------------------------------------------------------------------*/
  57. #ifdef AC_PROTO
  58. int b_alloc(BLKFILE *bp)
  59. #else
  60. int b_alloc(bp)
  61. BLKFILE *bp;
  62. #endif
  63. {
  64. #ifdef DEBUG
  65.     /* validate arguments */
  66.     if (!b_valid(bp)) {
  67.         BEPRINT;
  68.         errno = EINVAL;
  69.         return -1;
  70.     }
  71.  
  72.     /* check if not open */
  73.     if (!(bp->flags & BIOOPEN)) {
  74.         BEPRINT;
  75.         errno = BENOPEN;
  76.         return -1;
  77.     }
  78.  
  79.     /* check for memory leak */
  80.     if (bp->blockp != NULL || bp->blkbuf != NULL && !(bp->flags & BIOUSRBUF)) {
  81.         BEPRINT;
  82.         errno = BEPANIC;
  83.         return -1;
  84.     }
  85. #endif
  86.     /* check if not buffered */
  87.     if (bp->bufcnt == 0) {
  88.         return 0;
  89.     }
  90.  
  91.     /* allocate buffer storage (one extra block structure for header) */
  92.     bp->blockp = (block_t *)calloc(bp->bufcnt + 1, sizeof(block_t));
  93.     if (bp->blockp == NULL) {
  94.         BEPRINT;
  95.         errno = ENOMEM;
  96.         return -1;
  97.     }
  98.     if (!(bp->flags & BIOUSRBUF)) {
  99.         bp->blkbuf = calloc((size_t)1, bp->hdrsize + bp->bufcnt * bp->blksize);
  100.         if (bp->blkbuf == NULL) {
  101.             BEPRINT;
  102.             free(bp->blockp);
  103.             bp->blockp = NULL;
  104.             errno = ENOMEM;
  105.             return -1;
  106.         }
  107.     }
  108.  
  109.     return 0;
  110. }
  111.  
  112. /*man---------------------------------------------------------------------------
  113. NAME
  114.      b_blockp - pointer to block structure
  115.  
  116. SYNOPSIS
  117.      #include "blkio_.h"
  118.  
  119.      block_t *b_blockp(bp, i)
  120.      BLKFILE *bp;
  121.      size_t i;
  122.  
  123. DESCRIPTION
  124.      b_blockp returns a pointer to the ith block structure in the
  125.      buffer list of block file bp.  If bp is not a valid open block
  126.      file or i is not in the range [0..bp->bufcnt] the results are
  127.      undefined.  b_blockp is a macro.
  128.  
  129. ------------------------------------------------------------------------------*/
  130. /* b_blockp is defined in blkio_.h */
  131.  
  132. /*man---------------------------------------------------------------------------
  133. NAME
  134.      b_blkbuf - pointer to block buffer
  135.  
  136. SYNOPSIS
  137.      #include "blkio_.h"
  138.  
  139.      void *b_blkbuf(bp, i)
  140.      BLKFILE *bp;
  141.      size_t i;
  142.  
  143. DESCRIPTION
  144.      b_blkbuf returns a pointer to the ith buffer in the buffer list
  145.      of block file bp.  A value of zero for i indicates the header
  146.      buffer.  If bp is not a valid BLKFILE pointer to an open file or
  147.      i is not in the range [0..bp->bufcnt] the results are undefined.
  148.      b_blkbuf is a macro.
  149.  
  150. ------------------------------------------------------------------------------*/
  151. /* b_blkbuf is defined in blkio_.h */
  152.  
  153. /*man---------------------------------------------------------------------------
  154. NAME
  155.      b_free - free memory allocated for block file
  156.  
  157. SYNOPSIS
  158.      #include "blkio_.h"
  159.  
  160.      void b_free(bp)
  161.      BLKFILE *bp;
  162.  
  163. DESCRIPTION
  164.      The b_free function frees all memory allocated for block file bp.
  165.      If bp has a user-supplied buffer storage area, it is disconnected
  166.      from bp but is not freed.  On return from b_free, bp->blockp and
  167.      bp->blkbuf will be NULL.
  168.  
  169. SEE ALSO
  170.      b_alloc.
  171.  
  172. ------------------------------------------------------------------------------*/
  173. #ifdef AC_PROTO
  174. void b_free(BLKFILE *bp)
  175. #else
  176. void b_free(bp)
  177. BLKFILE *bp;
  178. #endif
  179. {
  180. #ifdef DEBUG
  181.     /* validate arguments */
  182.     if (!b_valid(bp)) {
  183.         BEPRINT;
  184.         return;
  185.     }
  186. #endif
  187.     /* free memory */
  188.     if (!(bp->flags & BIOUSRBUF)) {        /* if not user-supplied buf */
  189.         if (bp->blkbuf != NULL) {        /* free buffer */
  190.             free(bp->blkbuf);
  191.         }
  192.     }
  193.     bp->blkbuf = NULL;            /* disconnect buffer */
  194.     if (bp->blockp != NULL) {
  195.         free(bp->blockp);
  196.         bp->blockp = NULL;
  197.     }
  198.  
  199.     return;
  200. }
  201.  
  202. /*man---------------------------------------------------------------------------
  203. NAME
  204.      b_get - get block from block file
  205.  
  206. SYNOPSIS
  207.      #include "blkio_.h"
  208.  
  209.      int b_get(bp, i)
  210.      BLKFILE *bp;
  211.      size_t i;
  212.  
  213. DESCRIPTION
  214.      The b_get function reads a block from block file bp into the ith
  215.      buffer for that block file.  b_get reads the block identified by
  216.      the block number field of the block structure associated with
  217.      buffer i (i.e., b_blockp(bp, i)->bn); the zeroth buffer is
  218.      always used for the header.  The read flag is set and all others
  219.      cleared for buffer i.
  220.  
  221.      b_get will fail if one or more of the following is true:
  222.  
  223.      [EINVAL]       bp is not a valid BLKFILE pointer.
  224.      [EINVAL]       i is not in the range [0..bp->bufcnt].
  225.      [BEEOF]        End of file occured before end of block.
  226.      [BENBUF]       bp is not buffered.
  227.  
  228. SEE ALSO
  229.      b_put.
  230.  
  231. DIAGNOSTICS
  232.      Upon successful completion, a value of 0 is returned.  Otherwise,
  233.      a value of -1 is returned, and errno set to indicate the error.
  234.  
  235. ------------------------------------------------------------------------------*/
  236. #ifdef AC_PROTO
  237. int b_get(BLKFILE *bp, size_t i)
  238. #else
  239. int b_get(bp, i)
  240. BLKFILE *bp;
  241. size_t i;
  242. #endif
  243. {
  244. #ifdef DEBUG
  245.     /* validate arguments */
  246.     if (!b_valid(bp)) {
  247.         BEPRINT;
  248.         errno = EINVAL;
  249.         return -1;
  250.     }
  251.  
  252.     /* check if not open */
  253.     if (!(bp->flags & BIOOPEN)) {
  254.         BEPRINT;
  255.         errno = BENOPEN;
  256.         return -1;
  257.     }
  258.  
  259.     /* check if file is not buffered */
  260.     if (bp->bufcnt == 0) {
  261.         BEPRINT;
  262.         errno = BENBUF;
  263.         return -1;
  264.     }
  265.  
  266.     /* validate arguments */
  267.     if (i > bp->bufcnt) {
  268.         BEPRINT;
  269.         errno = EINVAL;
  270.         return -1;
  271.     }
  272.  
  273.     /* check if block number set */
  274.     if ((b_blockp(bp, i)->bn == 0) && (i != 0)) {
  275.         BEPRINT;
  276.         errno = BEPANIC;
  277.         return -1;
  278.     }
  279.  
  280.     /* check if block needs to be written to disk */
  281.     if (b_blockp(bp, i)->flags & BLKWRITE) {
  282.         BEPRINT;
  283.         errno = BEPANIC;
  284.         return -1;
  285.     }
  286. #endif
  287.     /* read block from file */
  288.     if (i == 0) {
  289.         if (b_ugetf(bp, (bpos_t)0, (size_t)0, b_blkbuf(bp, (size_t)0), bp->hdrsize) == -1) {
  290.             BEPRINT;
  291.             return -1;
  292.         }
  293.     } else {
  294.         if (b_ugetf(bp, b_blockp(bp, i)->bn, (size_t)0, b_blkbuf(bp, i), bp->blksize) == -1) {
  295.             BEPRINT;
  296.             return -1;
  297.         }
  298.     }
  299.  
  300.     /* set read flag and clear all others */
  301.     b_blockp(bp, i)->flags = BLKREAD;
  302.  
  303.     return 0;
  304. }
  305.  
  306. /*man---------------------------------------------------------------------------
  307. NAME
  308.      b_initlist - build linked list
  309.  
  310. SYNOPSIS
  311.      #include "blkio_.h"
  312.  
  313.      int b_initlist(bp)
  314.      BLKFILE *bp;
  315.  
  316. DESCRIPTION
  317.      The b_initlist function builds the linked list of buffers for
  318.      block file bp.  The buffer contents are deleted in the process.
  319.      A call to b_initlist should normally follow a call to b_alloc.
  320.  
  321.      b_initlist will fail if one or more of the following is true:
  322.  
  323.      [EINVAL]       bp is not a valid block file.
  324.  
  325. SEE ALSO
  326.      b_alloc.
  327.  
  328. DIAGNOSTICS
  329.      Upon successful completion, a value of 0 is returned.  Otherwise,
  330.      a value of -1 is returned, and errno set to indicate the error.
  331.  
  332. ------------------------------------------------------------------------------*/
  333. #ifdef AC_PROTO
  334. int b_initlist(BLKFILE *bp)
  335. #else
  336. int b_initlist(bp)
  337. BLKFILE *bp;
  338. #endif
  339. {
  340.     size_t i = 0;
  341.  
  342. #ifdef DEBUG
  343.     /* validate arguments */
  344.     if (!b_valid(bp)) {
  345.         BEPRINT;
  346.         errno = EINVAL;
  347.         return -1;
  348.     }
  349.  
  350.     /* check if not open */
  351.     if (!(bp->flags & BIOOPEN)) {
  352.         BEPRINT;
  353.         errno = BENOPEN;
  354.         return -1;
  355.     }
  356. #endif
  357.     /* initialize head and tail of list */
  358.     bp->most = 0;
  359.     bp->least = 0;
  360.  
  361.     /* check if not buffered */
  362.     if (bp->bufcnt == 0) {
  363.         return 0;
  364.     }
  365.  
  366.     /* initialize linked list */
  367.     bp->most = bp->bufcnt;
  368.     bp->least = 1;
  369.     for (i = 1; i <= bp->bufcnt; ++i) {
  370.         b_blockp(bp, i)->bn = 0;
  371.         b_blockp(bp, i)->flags = 0;
  372.         b_blockp(bp, i)->more = i + 1;
  373.         b_blockp(bp, i)->less = i - 1;
  374.     }
  375.     b_blockp(bp, bp->most)->more = 0;
  376.     b_blockp(bp, bp->least)->less = 0;
  377.  
  378.     /* initialize block structure for header */
  379.     b_blockp(bp, (size_t)0)->bn = 0;
  380.     b_blockp(bp, (size_t)0)->flags = 0;
  381.     b_blockp(bp, (size_t)0)->more = 0;
  382.     b_blockp(bp, (size_t)0)->less = 0;
  383.  
  384.     /* scrub buffer storage area */
  385.     memset(bp->blkbuf, 0, bp->hdrsize + bp->bufcnt * bp->blksize);
  386.  
  387.     return 0;
  388. }
  389.  
  390. /*man---------------------------------------------------------------------------
  391. NAME
  392.      b_mkmru - make most recently used block
  393.  
  394. SYNOPSIS
  395.      #include "blkio_.h"
  396.  
  397.      int b_mkmru(bp, i)
  398.      BLKFILE *bp;
  399.      size_t i;
  400.  
  401. DESCRIPTION
  402.      The b_mkmru function moves the ith block in the buffer list to
  403.      the most recently used end of the buffer list.
  404.  
  405.      b_mkmru will fail if one or more of the following is true:
  406.  
  407.      [EINVAL]       bp is not a valid block file.
  408.      [EINVAL]       i is not in the range [1..bp->bufcnt].
  409.      [BENBUF]       bp is not buffered.
  410.  
  411. DIAGNOSTICS
  412.      Upon successful completion, a value of 0 is returned.  Otherwise,
  413.      a value of -1 is returned, and errno set to indicate the error.
  414.  
  415. ------------------------------------------------------------------------------*/
  416. #ifdef AC_PROTO
  417. int b_mkmru(BLKFILE *bp, size_t i)
  418. #else
  419. int b_mkmru(bp, i)
  420. BLKFILE *bp;
  421. size_t i;
  422. #endif
  423. {
  424.     size_t more = 0;
  425.     size_t less = 0;
  426.  
  427. #ifdef DEBUG
  428.     /* validate arguments */
  429.     if (!b_valid(bp)) {
  430.         BEPRINT;
  431.         errno = EINVAL;
  432.         return -1;
  433.     }
  434.  
  435.     /* check if not open */
  436.     if (!(bp->flags & BIOOPEN)) {
  437.         BEPRINT;
  438.         errno = BENOPEN;
  439.         return -1;
  440.     }
  441.  
  442.     /* check if file is not buffered */
  443.     if (bp->bufcnt == 0) {
  444.         BEPRINT;
  445.         errno = BENBUF;
  446.         return -1;
  447.     }
  448.  
  449.     /* validate arguments */
  450.     if (i < 1 || i > bp->bufcnt) {
  451.         BEPRINT;
  452.         errno = EINVAL;
  453.         return -1;
  454.     }
  455. #endif
  456.     /* check block addresses */
  457.     more = b_blockp(bp, i)->more;
  458.     less = b_blockp(bp, i)->less;
  459.     if (more > bp->bufcnt || less > bp->bufcnt) {
  460.         BEPRINT;
  461.         errno = BEPANIC;
  462.         return -1;
  463.     }
  464.  
  465.     /* check if already most recently used */
  466.     if (more == 0) {
  467.         return 0;
  468.     }
  469.  
  470.     /* remove block i from linked list */
  471.     b_blockp(bp, more)->less = less;
  472.     if (less != 0) {
  473.         b_blockp(bp, less)->more = more;
  474.     } else {
  475.         bp->least = more;
  476.     }
  477.  
  478.     /* connect ith block as most recently used */
  479.     b_blockp(bp, i)->more = 0;
  480.     b_blockp(bp, i)->less = bp->most;
  481.     b_blockp(bp, bp->most)->more = i;
  482.     bp->most = i;
  483.  
  484.     return 0;
  485. }
  486.  
  487. /*man---------------------------------------------------------------------------
  488. NAME
  489.      b_put - put block into block file
  490.  
  491. SYNOPSIS
  492.      #include "blkio_.h"
  493.  
  494.      int b_put(bp, i)
  495.      BLKFILE *bp;
  496.      size_t i;
  497.  
  498. DESCRIPTION
  499.      The b_put function writes a block from the ith buffer of block
  500.      file bp to the file.  b_put writes to the block identified by
  501.      the block number field of the block structure associated with
  502.      buffer i (i.e., b_blockp(bp, i)->bn); the zeroth buffer is
  503.      always used for the header.  If the write flag is not set,
  504.      nothing is written.  After writing, the write flag is cleared.
  505.  
  506.      b_put will fail if one or more of the following is true:
  507.  
  508.      [EINVAL]       bp is not a valid block file.
  509.      [EINVAL]       i is not in the range [0..bp->bufcnt].
  510.      [BENBUF]       bp is not buffered.
  511.  
  512. SEE ALSO
  513.      b_get.
  514.  
  515. DIAGNOSTICS
  516.      Upon successful completion, a value of 0 is returned.  Otherwise,
  517.      a value of -1 is returned, and errno set to indicate the error.
  518.  
  519. ------------------------------------------------------------------------------*/
  520. #ifdef AC_PROTO
  521. int b_put(BLKFILE *bp, size_t i)
  522. #else
  523. int b_put(bp, i)
  524. BLKFILE *bp;
  525. size_t i;
  526. #endif
  527. {
  528. #ifdef DEBUG
  529.     /* validate arguments */
  530.     if (!b_valid(bp)) {
  531.         BEPRINT;
  532.         errno = EINVAL;
  533.         return -1;
  534.     }
  535.  
  536.     /* check if not open */
  537.     if (!(bp->flags & BIOOPEN)) {
  538.         BEPRINT;
  539.         errno = BENOPEN;
  540.         return -1;
  541.     }
  542.  
  543.     /* check if file is not buffered */
  544.     if (bp->bufcnt == 0) {
  545.         BEPRINT;
  546.         errno = BENBUF;
  547.         return -1;
  548.     }
  549.  
  550.     /* validate arguments */
  551.     if (i > bp->bufcnt) {
  552.         BEPRINT;
  553.         errno = EINVAL;
  554.         return -1;
  555.     }
  556. #endif
  557.     /* check if block doesn't need to be written to disk */
  558.     if (!(b_blockp(bp, i)->flags & BLKWRITE)) {
  559.         return 0;
  560.     }
  561.  
  562.     /* check for inconsistent read flag setting */
  563.     if (!(b_blockp(bp, i)->flags & BLKREAD)) {
  564.         BEPRINT;
  565.         errno = BEPANIC;
  566.         return 0;
  567.     }
  568.  
  569.     /* write block to disk */
  570.     if (i == 0) {
  571.         if (b_uputf(bp, (bpos_t)0, (size_t)0, b_blkbuf(bp, (size_t)0), bp->hdrsize) == -1) {
  572.             BEPRINT;
  573.             return -1;
  574.         }
  575.     } else {
  576.         if (b_uputf(bp, b_blockp(bp, i)->bn, (size_t)0, b_blkbuf(bp, i), bp->blksize) == -1) {
  577.             BEPRINT;
  578.             return -1;
  579.         }
  580.     }
  581.  
  582.     /* clear all but read flag */
  583.     b_blockp(bp, i)->flags = BLKREAD;
  584.  
  585.     return 0;
  586. }
  587.  
  588. /*man---------------------------------------------------------------------------
  589. NAME
  590.      b_valid - validate block file pointer
  591.  
  592. SYNOPSIS
  593.      #include "blkio_.h"
  594.  
  595.      bool b_valid(bp)
  596.      BLKFILE *bp;
  597.  
  598. DESCRIPTION
  599.      The b_valid function determines if bp is a valid BLKFILE pointer.
  600.      If valid, the TRUE is returned.  If not, then FALSE is returned.
  601.  
  602. ------------------------------------------------------------------------------*/
  603. #ifdef AC_PROTO
  604. bool b_valid(const BLKFILE *bp)
  605. #else
  606. bool b_valid(bp)
  607. const BLKFILE *bp;
  608. #endif
  609. {
  610.     if (bp < biob || bp > (biob + BOPEN_MAX - 1)) {
  611.         return FALSE;
  612.     }
  613.     if (((char *)bp - (char *)biob) % sizeof(*biob) != 0) {
  614.         return FALSE;
  615.     }
  616.  
  617.     return TRUE;
  618. }
  619.